home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / datatypes / bmp_datatype / source / getbmp.c < prev    next >
C/C++ Source or Header  |  1995-08-11  |  8KB  |  364 lines

  1. /*
  2. ** our include
  3. */
  4.  
  5. #include "getbmp.h"
  6.  
  7. /*
  8. ** easy access of a char-array as a "structure" (IJG sources v5.0b)
  9. */
  10.  
  11. #define UCH(x) \
  12.   ((int) (x))
  13.  
  14. #define GET_2B(array,offset) \
  15.   ((unsigned int) UCH(array[offset]) + \
  16.    (((unsigned int) UCH(array[offset+1])) << 8))
  17.  
  18. #define GET_4B(array,offset) \
  19.   ((ULONG) UCH(array[offset]) + \
  20.    (((ULONG) UCH(array[offset+1])) << 8) + \
  21.    (((ULONG) UCH(array[offset+2])) << 16) + \
  22.    (((ULONG) UCH(array[offset+3])) << 24))
  23.  
  24. /*
  25. ** get dt attribute(s)
  26. */
  27.  
  28. ULONG set_dt_attrs(Object *obj, ULONG data, ...)
  29. {
  30.   return (SetDTAttrsA(obj,NULL,NULL,(struct TagItem *)&data));
  31. }
  32.  
  33. /*
  34. ** get dt attribute(s)
  35. */
  36.  
  37. ULONG get_dt_attrs(Object *obj, ULONG data, ...)
  38. {
  39.   return (GetDTAttrsA(obj,(struct TagItem *)&data));
  40. }
  41.  
  42. /*
  43. ** expand every bit to a byte
  44. */
  45.  
  46. VOID convert_1bit(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width)
  47. {
  48.   UBYTE *p=outbuf,c;
  49.   int i,j;
  50.  
  51.   for(i=width/8; i>0; i--)
  52.   {
  53.     for(c=*pixelbuf++,j=7; j>=0; j--)
  54.     {
  55.       *p++ = ((c & 0x80) ? 1 : 0);
  56.       c <<= 1;
  57.     }
  58.   }
  59.   if ((i=width%8))
  60.   {
  61.     for(c=*pixelbuf,j=7; i>0; j--,i--)
  62.     {
  63.       *p++ = ((c & 0x80) ? 1 : 0);
  64.       c <<= 1;
  65.     }
  66.   }
  67. }
  68.  
  69. /*
  70. ** expand every 4 bits to a byte
  71. */
  72.  
  73. VOID convert_4bit(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width)
  74. {
  75.   UBYTE *p=outbuf,c;
  76.   int i;
  77.  
  78.   for(i=width/2; i>0; i--)
  79.   {
  80.     c = *pixelbuf++;
  81.     *p++ = (c >> 4); /* ((c & 0xf0) >> 4); */
  82.     *p++ = (c & 0xf);
  83.   }
  84.   if (width & 1)
  85.   {
  86.     c = *pixelbuf; *p = (c >> 4); /* ((c & 0xf0) >> 4); */
  87.   }
  88. }
  89.  
  90. /*
  91. ** perform a simple copy (outbuf is WritePixelLine8() aware..)
  92. */
  93.  
  94. VOID convert_8bit(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width)
  95. {
  96.   CopyMem(pixelbuf,outbuf,width);
  97. }
  98.  
  99. /*
  100. ** create the bitmap
  101. */
  102.  
  103. int decode_bmp_picture(Object *obj, APTR pool, BPTR fh, struct BitMapHeader *bmhd, ULONG title)
  104. {
  105.   register VOID (*convert)(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width) REG(a3);
  106.   struct BitMap *tbm,*bm;
  107.   struct RastPort trp,rp;
  108.   UBYTE *albuff,*buffer,*p;
  109.   ULONG modeid,padwidth,width,height,depth,large;
  110.   int line,index,success=FALSE;
  111.  
  112.   width = bmhd->bmh_Width; height = bmhd->bmh_Height; depth = bmhd->bmh_Depth;
  113.  
  114.   if ((bm=AllocBitMap(width,height,depth,BMF_CLEAR|BMF_DISPLAYABLE,NULL)) != NULL)
  115.   {
  116.     InitRastPort(&rp); rp.BitMap = bm;
  117.  
  118.     if ((tbm=AllocBitMap(width,1,depth,BMF_CLEAR,NULL)) != NULL)
  119.     {
  120.       InitRastPort(&trp); trp.BitMap = tbm;
  121.  
  122.       if ((albuff=AllocPooled(pool,((width+15)&~15))) != NULL)
  123.       {
  124.         padwidth = ((((width * depth) + 31) & ~31) / 8);
  125.  
  126.         large = padwidth * height;
  127.  
  128.         if ((buffer=AllocPooled(pool,large)) != NULL)
  129.         {
  130.           if (Read(fh,buffer,large) != large)
  131.           {
  132.             buffer=NULL;
  133.           }
  134.         }
  135.         else
  136.         {
  137.           buffer=AllocPooled(pool,padwidth); large=0;
  138.         }
  139.  
  140.         if (buffer != NULL)
  141.         {
  142.           convert = convert_1bit;
  143.           if (depth != 1)
  144.           {
  145.             convert = convert_4bit;
  146.             if (depth != 4)
  147.               convert = convert_8bit;
  148.           }
  149.  
  150.           for (line=(height-1),index=0; line>=0; index++,line--)
  151.           {
  152.             if (large)
  153.               p=&buffer[index*padwidth];
  154.             else
  155.               if (Read(fh,(p=buffer),padwidth) != padwidth)
  156.                 goto error;
  157.             (*convert)(p,albuff,width);
  158.             WritePixelLine8(&rp,0,line,width,albuff,&trp);
  159.           }
  160.  
  161.           modeid = LORES_KEY;
  162.           if ((UWORD)width >= 640)
  163.             modeid = HIRES;
  164.           if ((UWORD)height >= 400)
  165.             modeid |= LACE;
  166.  
  167.           set_dt_attrs(obj,
  168.                        DTA_ObjName,      title,
  169.                        DTA_NominalHoriz, width,
  170.                        DTA_NominalVert,  height,
  171.                        PDTA_BitMap,      bm,
  172.                        PDTA_ModeID,      modeid,
  173.                        TAG_DONE);
  174.  
  175.           success = TRUE;
  176.  
  177.         }
  178.  
  179.       }
  180. error:
  181.       FreeBitMap(tbm);
  182.     }
  183.  
  184.     if (!success)
  185.       FreeBitMap(bm);
  186.   }
  187.  
  188.   return success;
  189. }
  190.  
  191. /*
  192. ** extract all required information from the bmp header
  193. */
  194.  
  195. int read_bmp_header(Object *obj, APTR pool, BPTR fh, struct BitMapHeader *bmhd)
  196. {
  197.   UBYTE bmpfileheader[14+64],*coltab,*cmap;
  198.  
  199.   #define bmpinfoheader (bmpfileheader+14)
  200.  
  201.   LONG *cregs;
  202.   LONG biCompression;
  203.   LONG biClrUsed;
  204.   LONG biPlanes;
  205.   LONG bfOffBits;
  206.   LONG headerSize;
  207.   LONG bPad;
  208.   LONG cmapentrysize;
  209.   LONG coltabsize;
  210.   int i;
  211.  
  212.   if (Read(fh,bmpfileheader,18) != 18)
  213.     return FALSE;
  214.  
  215.   if (((UWORD)GET_2B(bmpfileheader,0)) != 0x4D42)
  216.     return FALSE;
  217.  
  218.   bfOffBits  = (LONG) GET_4B(bmpfileheader,10);
  219.   headerSize = (LONG) GET_4B(bmpinfoheader, 0);
  220.  
  221.   if (headerSize < 12 || headerSize > 64)
  222.     return FALSE;
  223.  
  224.   if (Read(fh,bmpinfoheader+4,headerSize-4) != (headerSize-4))
  225.     return FALSE;
  226.  
  227.   switch(headerSize)
  228.   {
  229.     case 12: /* OS/2 1.x */
  230.       bmhd->bmh_Width  = (WORD) GET_2B(bmpinfoheader, 4);
  231.       bmhd->bmh_Height = (WORD) GET_2B(bmpinfoheader, 6);
  232.       biPlanes         =        GET_2B(bmpinfoheader, 8);
  233.       bmhd->bmh_Depth  = (WORD) GET_2B(bmpinfoheader,10);
  234.       biCompression    =        0;
  235.       biClrUsed        =        0;
  236.       switch (bmhd->bmh_Depth)
  237.       {
  238.         case 1:
  239.         case 4:
  240.         case 8:
  241.           cmapentrysize = 3;
  242.           break;
  243.         case 24:
  244.           cmapentrysize = 0;
  245.           break;
  246.         default:
  247.           cmapentrysize = 0;
  248.           break;
  249.       }
  250.       break;
  251.     case 40: /* Windows 3.x or OS/2 2.x */
  252.     case 64:
  253.       bmhd->bmh_Width  = (WORD) GET_4B(bmpinfoheader, 4);
  254.       bmhd->bmh_Height = (WORD) GET_4B(bmpinfoheader, 8);
  255.       biPlanes         =        GET_2B(bmpinfoheader,12);
  256.       bmhd->bmh_Depth  = (WORD) GET_2B(bmpinfoheader,14);
  257.       biCompression    =        GET_4B(bmpinfoheader,16);
  258.       biClrUsed        =        GET_4B(bmpinfoheader,32);
  259.       switch (bmhd->bmh_Depth)
  260.       {
  261.         case 1:
  262.         case 4:
  263.         case 8:
  264.           cmapentrysize = 4;
  265.           break;
  266.         case 24:
  267.           cmapentrysize = 0;
  268.           break;
  269.         default:
  270.           cmapentrysize = 0;
  271.           break;
  272.       }
  273.       break;
  274.     default:
  275.       cmapentrysize = 0;
  276.       break;
  277.   }
  278.  
  279.   bmhd->bmh_PageWidth  = bmhd->bmh_Width;
  280.   bmhd->bmh_PageHeight = bmhd->bmh_Height;
  281.  
  282.   if (biPlanes != 1 || biCompression != 0 || cmapentrysize == 0)
  283.     return FALSE;
  284.  
  285.   if (biClrUsed <= 0)
  286.     biClrUsed = 1L << bmhd->bmh_Depth;
  287.  
  288.   if (biClrUsed > 256)
  289.     return FALSE;
  290.  
  291.   (void)set_dt_attrs(obj, PDTA_NumColors,(ULONG)biClrUsed, TAG_DONE);
  292.  
  293.   if ((get_dt_attrs(obj, PDTA_ColorRegisters,(ULONG)&cmap,PDTA_CRegs,(ULONG)&cregs, TAG_DONE)) != 2)
  294.     return FALSE;
  295.  
  296.   coltabsize = biClrUsed * cmapentrysize;
  297.  
  298.   if ((coltab=AllocPooled(pool,coltabsize)) == NULL)
  299.     return FALSE;
  300.  
  301.   if (Read(fh,coltab,coltabsize) != coltabsize)
  302.     return FALSE;
  303.  
  304.   /*
  305.   ** do not use "struct ColorRegister" for cmap since with the amiga port
  306.   ** of gcc a sizeof() for this structure is four and not three.. oh well
  307.   */
  308.  
  309.   for(i=0; i<biClrUsed; cmap+=3,cregs+=3,coltab+=cmapentrysize,i++)
  310.   {
  311.     UBYTE r,g,b;
  312.  
  313.     r = coltab[2];
  314.     cmap[0] = r; cregs[0] = r << 24;
  315.     g = coltab[1];
  316.     cmap[1] = g; cregs[1] = g << 24;
  317.     b = coltab[0];
  318.     cmap[2] = b; cregs[2] = b << 24;
  319.   }
  320.  
  321.   bPad = bfOffBits - (14 + headerSize + coltabsize);
  322.  
  323.   for(;bPad>0;)
  324.   {
  325.     LONG size = (bPad < sizeof(bmpfileheader) ? bPad : sizeof(bmpfileheader));
  326.     if (Read(fh,&bmpfileheader[0],size) != size)
  327.       break;
  328.     bPad -= size;
  329.   }
  330.  
  331.   return (bPad == 0 ? TRUE : FALSE);
  332. }
  333.  
  334. /*
  335. ** load the picture
  336. */
  337.  
  338. int GetBMP(Class *cl, Object *obj, struct TagItem *attrs)
  339. {
  340.   struct BitMapHeader *bmhd;
  341.   LONG ioerr;
  342.   APTR pool;
  343.   BPTR fh;
  344.   int success=FALSE;
  345.  
  346.   if ((pool=CreatePool(MEMF_ANY,1024,1024)) != NULL)
  347.   {
  348.     if ((get_dt_attrs(obj, DTA_Handle,&fh,PDTA_BitMapHeader,&bmhd, TAG_DONE) == 2) && fh)
  349.       for(;;)
  350.       {
  351.         ioerr=ERROR_OBJECT_WRONG_TYPE;
  352.         if ((success=read_bmp_header(obj,pool,fh,bmhd)) != FALSE)
  353.         {
  354.           if ((success=decode_bmp_picture(obj,pool,fh,bmhd,GetTagData(DTA_Name,NULL,attrs))) != FALSE)
  355.             break;
  356.           ioerr=ERROR_NO_FREE_STORE;
  357.         }
  358.         SetIoErr(ioerr); break;
  359.       }
  360.     DeletePool(pool);
  361.   }
  362.   return success;
  363. }
  364.